package com.aegis.manage.service.auth.user;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.aegis.common.mybatis.model.PageResult;
import com.aegis.common.redis.util.RedisUtil;
import com.aegis.common.utils.AssertUtil;
import com.aegis.core.constants.AegisTokenRedisConstants;
import com.aegis.core.manager.AegisAppManager;
import com.aegis.core.manager.AegisDataCleanManager;
import com.aegis.core.manager.AegisUserPermissionManager;
import com.aegis.core.model.*;
import com.aegis.manage.api.request.QueryUserInfoPageRequest;
import com.aegis.manage.api.vo.AppDetailVO;
import com.aegis.manage.api.vo.AuthUserInfoVO;
import com.aegis.manage.mapper.AuthUserInfoMapper;
import com.aegis.manage.model.dos.AuthApp;
import com.aegis.manage.model.dos.AuthUserInfo;
import com.aegis.manage.service.auth.app.AuthAppService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * @Author wuweixin
 * @Version 1.0
 * @Descritube
 */
@Service
@Slf4j
public class UserPermissionServiceImpl implements UserPermissionService {

    @Autowired
    private AuthAppService authAppService;

    @Autowired
    private AuthUserInfoMapper authUserInfoMapper;

    public static final int BATCH_SIZE = 1;

    @Override
    public void syncLoginUser() {
        List<AegisAppInfo> appInfos = AegisAppManager.getAppInfos();
        for (AegisAppInfo appInfo : appInfos) {
            String appId = appInfo.getAppId();
            try {
                AegisDataCleanManager.scanLoginUser(appId, BATCH_SIZE, (Function<HashScanResult<AegisSession>, Boolean>)
                        hashScanResult -> {
                    Map<String, AegisSession> map = hashScanResult.getMap();
                    if (map == null || map.isEmpty()) {
                        return true;
                    }
                    map.forEach((s, value) -> {
                        AuthUserInfo authUserInfo = authUserInfoMapper.selectOne(new LambdaQueryWrapper<AuthUserInfo>()
                                .eq(AuthUserInfo::getUserId, s)
                                .eq(AuthUserInfo::getAppId, appId)
                                .last("limit 1"));
                        boolean isInsert = false;
                        if (authUserInfo == null) {
                            isInsert = true;
                            authUserInfo = new AuthUserInfo();
                            authUserInfo.setAppId(appId);
                            authUserInfo.setUserId(s);
                            AuthApp authApp = authAppService.selectAppByAppId(appId);
                            if (authApp == null) {
                                log.info("不存在的应用id {}", appId);
                                RedisUtil.hdel(AegisTokenRedisConstants.getDataCleanLoginUser(appId), s);
                                return;
                            }
                            authUserInfo.setSysAppId(authApp.getId());
                        }
                        authUserInfo.setAccount(value.getAccount());
                        authUserInfo.setLastLoginIp(value.getLoginIp());
                        authUserInfo.setLastLoginTime(value.getCreateTime());
                        authUserInfo.setLastLoginDevice(value.getLoginDevice());
                        if (isInsert) {
                            authUserInfoMapper.insert(authUserInfo);
                        } else {
                            authUserInfoMapper.updateById(authUserInfo);
                        }
                        RedisUtil.hdel(AegisTokenRedisConstants.getDataCleanLoginUser(appId), s);
                    });

                    return true;
                });
            } catch (Exception e) {
                log.error("数据清洗失败", e);
            }
        }
    }

    @Override
    public List<AegisAppGroupPermission> queryUserGroupPermission(String sysAppId) {
        AppDetailVO appDetailVO = authAppService.selectAppDetailById(sysAppId);
        AssertUtil.operateFailed(appDetailVO == null, "不存在的应用");
        return AegisUserPermissionManager.getAppGroup(appDetailVO.getAppId());
    }

    @Override
    public List<AegisUserApi> queryUserGroupApi(String sysAppId, String groupKey) {
        AppDetailVO appDetailVO = authAppService.selectAppDetailById(sysAppId);
        AssertUtil.operateFailed(appDetailVO == null, "不存在的应用");
        List<AegisAppGroupPermission> appGroup = AegisUserPermissionManager
                .getAppGroup(appDetailVO.getAppId(), groupKey);
        if (CollectionUtil.isEmpty(appGroup)) {
            return null;
        }
        return appGroup.get(0).getApis();
    }

    @Override
    public PageResult<AuthUserInfoVO> queryUserInfoPage(QueryUserInfoPageRequest request) {
        PageResult<AuthUserInfo> exchange = PageResult.exchange(authUserInfoMapper.selectPage(new Page<>(request.getCurrent(), request.getSize()),
                new LambdaQueryWrapper<AuthUserInfo>()
                        .eq(StrUtil.isNotBlank(request.getId()), AuthUserInfo::getSysAppId, request.getId())
                        .and(StrUtil.isNotBlank(request.getKeywords()), authUserInfoLambdaQueryWrapper -> {
                            authUserInfoLambdaQueryWrapper.like(AuthUserInfo::getAccount, request.getKeywords())
                                    .or()
                                    .like(AuthUserInfo::getUserId, request.getKeywords());
                        })
                        .orderByDesc(AuthUserInfo::getLastLoginTime)));
        return exchange.exchange(exchange, authUserInfo -> {
            AuthUserInfoVO authUserInfoVO = new AuthUserInfoVO();
            BeanUtil.copyProperties(authUserInfo, authUserInfoVO);
            return authUserInfoVO;
        });
    }

}
